package com.hz.web.util;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StringUtils;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * Date Utility Class used to convert Strings to Dates and Timestamps
 *
 * @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a>
 *         Modified by <a href="mailto:dan@getrolling.com">Dan Kibler </a>
 *         to correct time pattern. Minutes should be mm not MM (MM is month).
 */
public class DateUtil {
    private static Log log = LogFactory.getLog(DateUtil.class);
    private static final String TIME_PATTERN = "HH:mm";


    /**
     * Checkstyle rule: utility classes should not have public constructor
     */
    public DateUtil() {
    }

    public static String getTimestampToString(Timestamp obj) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        String str = df.format(obj);
        return str;
    }

    public static String getTimestampToString(String formatPattern, Timestamp obj) {
        SimpleDateFormat df = new SimpleDateFormat(formatPattern);
        String str = df.format(obj);
        return str;
    }

    public static Timestamp getStringToTimestamp(String str) {
        Timestamp ts = Timestamp.valueOf(str);
        return ts;
    }

    public static Date strToDate(String str, String pattern) {
        Date dateTemp = null;
        SimpleDateFormat formater2 = new SimpleDateFormat(pattern);
        try {
            dateTemp = formater2.parse(str);
        } catch (Exception e) {
            log.error("exception in convert string to date!");
        }
        return dateTemp;
    }

    /**
     * Return default datePattern (yyyy-MM-dd)
     *
     * @return a string representing the date pattern on the UI
     */
    public static String getDatePattern() {
        return "yyyy-MM-dd";
    }

    public static String getDateTimePattern() {
        return DateUtil.getDatePattern() + " HH:mm:ss.S";
    }

    public static String getDateTimePattern2() {
        return DateUtil.getDatePattern() + " HH:mm:ss";
    }

    /**
     * This method attempts to convert an Oracle-formatted date
     * in the form dd-MMM-yyyy to yyyy-MM-dd.
     *
     * @param aDate date from database as a string
     * @return formatted string for the ui
     */
    public static String getDate(Date aDate) {
        SimpleDateFormat df;
        String returnValue = "";

        if (aDate != null) {
            df = new SimpleDateFormat(getDatePattern());
            returnValue = df.format(aDate);
        }

        return (returnValue);
    }

    /**
     * This method generates a string representation of a date/time
     * in the format you specify on input
     *
     * @param aMask   the date pattern the string is in
     * @param strDate a string representation of a date
     * @return a converted Date object
     * @throws ParseException when String doesn't match the expected format
     * @see SimpleDateFormat
     */
    public static Date convertStringToDate(String aMask, String strDate) throws ParseException {
        SimpleDateFormat df;
        Date date;
        df = new SimpleDateFormat(aMask);

        if (log.isDebugEnabled()) {
            log.debug("converting '" + strDate + "' to date with mask '" + aMask + "'");
        }

        try {
            date = df.parse(strDate);
        } catch (ParseException pe) {
            //log.error("ParseException: " + pe);
            throw new ParseException(pe.getMessage(), pe.getErrorOffset());
        }

        return (date);
    }

    //把Date 格式化后返回 Date
    public static Date formatDateToDate(Date date, String format) throws ParseException {
        if (StringUtils.isEmpty(format)) {
            format = "yyyy-MM-dd";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        String dd = sdf.format(date);
        Date ddd = null;
        try {
            ddd = sdf.parse(dd);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return ddd;
    }

    /**
     * This method returns the current date time in the format:
     * yyyy-MM-dd HH:MM a
     *
     * @param theTime the current time
     * @return the current date/time
     */
    public static String getTimeNow(Date theTime) {
        return getDateTime(TIME_PATTERN, theTime);
    }

    /**
     * This method returns the current date in the format: yyyy-MM-dd
     *
     * @return the current date
     * @throws ParseException when String doesn't match the expected format
     */
    public static Calendar getToday() throws ParseException {
        Date today = new Date();
        SimpleDateFormat df = new SimpleDateFormat(getDatePattern());

        // This seems like quite a hack (date -> string -> date),
        // but it works ;-)
        String todayAsString = df.format(today);
        Calendar cal = new GregorianCalendar();
        cal.setTime(convertStringToDate(todayAsString));

        return cal;
    }

    public static Calendar getCurrentDay() throws ParseException {
        Calendar cal = Calendar.getInstance();
        return cal;

    }

    /**
     * This method generates a string representation of a date's date/time
     * in the format you specify on input
     *
     * @param aMask the date pattern the string is in
     * @param aDate a date object
     * @return a formatted string representation of the date
     * @see SimpleDateFormat
     */
    public static String getDateTime(String aMask, Date aDate) {
        SimpleDateFormat df = null;
        String returnValue = "";

        if (aDate == null) {
            log.error("aDate is null!");
        } else {
            df = new SimpleDateFormat(aMask);
            returnValue = df.format(aDate);
        }

        return (returnValue);
    }

    /**
     * This method generates a string representation of a date based
     * on the System Property 'dateFormat'
     * in the format you specify on input
     *
     * @param aDate A date to convert
     * @return a string representation of the date
     */
    public static String convertDateToString(Date aDate) {
        return getDateTime(getDatePattern(), aDate);
    }

    /**
     * This method converts a String to a date using the datePattern
     *
     * @param strDate the date to convert (in format yyyy-MM-dd)
     * @return a date object
     * @throws ParseException when String doesn't match the expected format
     */
    public static Date convertStringToDate(String strDate) throws ParseException {
        Date aDate = null;
        try {
            if (log.isDebugEnabled()) {
                log.debug("converting date with pattern: " + getDatePattern());
            }
            aDate = convertStringToDate(getDatePattern(), strDate);
        } catch (ParseException pe) {
            log.error("Could not convert '" + strDate + "' to a date, throwing exception");
            log.error(pe);
            throw new ParseException(pe.getMessage(), pe.getErrorOffset());
        }

        return aDate;
    }

    /**
     * @param aDate
     * @return
     */
    public static String convertDateToString(String pattern, Date aDate) {
        return getDateTime(pattern, aDate);
    }

    public static Date getRelativeDate(Date startDate, int day) {
        Calendar calendar = Calendar.getInstance();
        try {
            calendar.setTime(startDate);
            calendar.add(Calendar.DAY_OF_MONTH, day);
            return calendar.getTime();
        } catch (Exception e) {
            log.error(e);
            return startDate;
        }
    }

    public static int getDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.DAY_OF_WEEK) - 1;
    }

    public static int countDays(String beginStr, String endStr, String Foramt) {
        Date end = strToDate(endStr, Foramt);
        Date begin = strToDate(beginStr, Foramt);
        long times = end.getTime() - begin.getTime();
        return (int) (times / 60 / 60 / 1000 / 24);
    }

    public static int countDays(Date beginDate, Date endDate) {
        long times = endDate.getTime() - beginDate.getTime();
        return (int) (times / 60 / 60 / 1000 / 24);
    }

    // 日期转换成字符串
    public static String dateToStr(Date date,
                                   String format) {
        // yyyy-MM-dd HH:mm:ss
        if (StringUtils.isEmpty(format)) {
            format = "yyyy-MM-dd";
        }
        SimpleDateFormat sf = new SimpleDateFormat(format);
        String str = sf.format(date);
        return str;
    }

    // 毫秒转换为日期
    public static String longToDateStr(long millis, String format) {
        if (StringUtils.isEmpty(format)) {
            format = "yyyy-MM-dd HH:mm:ss";
        }
        SimpleDateFormat sf = new SimpleDateFormat(format);
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(millis);
        return sf.format(calendar.getTime());
    }


    // 指定日期加减月数
    public static Date calculateDate(Date date, int months) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        //c.add(c.YEAR, -2);// 属性很多也有月等等，可以操作各种时间日期
        // c.add(c.DATE, -1);
        c.add(Calendar.MONTH, months);
        Date temp_date = c.getTime();

        return temp_date;
    }

    // 指定日期加减天数
    public static Date calculateDateAddDay(Date date, int days) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.DATE, days);
        Date temp_date = c.getTime();

        return temp_date;
    }

    // 指定日期加减分钟
    public static Date calculateDateAddMinute(Date date, int minute) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.MINUTE, minute);
        Date temp_date = c.getTime();

        return temp_date;
    }

    // 指定日期加减小时
    public static Date calculateDateAddHour(Date date, int hour) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.HOUR, hour);
        Date temp_date = c.getTime();

        return temp_date;
    }

    /**
     * 获取月份的天数
     *
     * @param date
     * @return
     */
    public static int getMonthDayNum(Date date) {
        int year = date.getYear();
        int month = date.getMonth() + 1;
        int monthDay = 30;

        switch (month) {
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                monthDay = 31;
                break;
            // 对于2月份需要判断是否为闰年
            case 2:
                if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
                    monthDay = 29;

                    System.out.println(month + "月份有：29天");
                    break;
                } else {
                    monthDay = 28;
                    System.out.println(month + "月份有：28天");
                    break;
                }
            case 4:
            case 6:
            case 9:
            case 11:
                System.out.println(month + "月份有：30天");
                break;
            default:
                System.out.println("默认为30天");
                break;
        }
        return monthDay;
    }


    public static String getCronExpressionByDate(Date date) {
        SimpleDateFormat df = new SimpleDateFormat("ss mm HH dd MM ? yyyy");
        return df.format(date);
    }

    public static boolean ifLeapYear(int year) {
        if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) {
            return true;
        } else {
            return false;
        }
    }

    //计算两个日期之间的月数。 如：2014-7到2014-10 返回的monthNum=3
    public static int getMonthCount(Date startDate, Date endDate) throws ParseException {
        String startDateStr = DateUtil.dateToStr(startDate, "MM");
        String endDateStr = DateUtil.dateToStr(endDate, "MM");

        System.out.println(startDateStr);
        System.out.println(endDateStr);
        int monthNum = Integer.parseInt(endDateStr) - Integer.parseInt(startDateStr);
        if (monthNum < 0) {
            monthNum = monthNum + 12;
        }

        System.out.print(monthNum);
        return monthNum;
    }

    //时间比较函数
    public static int dateCompare(Date startDate, Date endDate, String format) {
        if (StringUtils.isEmpty(format)) {
            format = "yyyy-MM-dd HH:mm:ss";
        }
        String startDateStr = dateToStr(startDate, format);
        String endDateStr = dateToStr(endDate, format);
        DateFormat df = new SimpleDateFormat(format);
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        try {
            c1.setTime(df.parse(startDateStr));
            c2.setTime(df.parse(endDateStr));
        } catch (ParseException e) {
            System.err.println("格式不正确");
        }
        int result = c1.compareTo(c2);
      /*  if (result == 0)
            System.out.println("c1相等c2");
        else if (result < 0)
            System.out.println("c1小于c2");
        else
            System.out.println("c1大于c2");*/

        return result;
    }


    /**
     * 获取指定时间的00 00 00
     * @param date
     * @return
     */
    public static Date getFirstDateByDate(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        //将小时至0
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        //将分钟至0
        calendar.set(Calendar.MINUTE, 0);
        //将秒至0
        calendar.set(Calendar.SECOND,0);
        //将毫秒至0
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }
    /**
     * 获取指定时间的23：59：59
     * @return
     */
    public static Date getLastDateByDate(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        //将小时至0
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        //将分钟至0
        calendar.set(Calendar.MINUTE, 0);
        //将秒至0
        calendar.set(Calendar.SECOND,0);
        //将毫秒至0
        calendar.set(Calendar.MILLISECOND, 0);
        //获得当前当天
        Date sdate = calendar.getTime();
        //将当前天加1；
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        //在当昨天的基础上减去1毫秒
        calendar.add(Calendar.MILLISECOND, -1);
        return calendar.getTime();
    }

    public static String getPreDate() {
        Calendar calendar = Calendar.getInstance();//此时打印它获取的是系统当前时间
        calendar.add(Calendar.DATE, -1);//得到前一天
        return new SimpleDateFormat("yyyyMMdd").format(calendar.getTime());
    }

    public static String getToDate() {
        Calendar calendar = Calendar.getInstance();//此时打印它获取的是系统当前时间
        return new SimpleDateFormat("yyyyMMdd").format(calendar.getTime());
    }


    /**
     * 计算两个日期之间相差的天数
     * @param smdate 较早的时间
     * @param bdate  较晚的时间
     * @return 相差天数
     * @throws ParseException
     */
    public static int daysBetween(Date smdate,Date bdate) throws ParseException
    {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        smdate=sdf.parse(sdf.format(smdate));
        bdate=sdf.parse(sdf.format(bdate));
        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();
        long between_days=(time2-time1)/(1000*3600*24);

        return Integer.parseInt(String.valueOf(between_days));
    }

    /**
     * 指定日期加上天数后的日期
     * @param num        为增加的天数
     * @param newDate    创建时间
     * @param dateFormat 日期格式
     * @return
     * @throws ParseException
     */
    public static String plusDay(int num, String newDate, String dateFormat) throws ParseException{
        SimpleDateFormat format = new SimpleDateFormat(dateFormat);
        Date currdate = format.parse(newDate);
        Calendar ca = Calendar.getInstance();
        ca.setTime(currdate);
        ca.add(Calendar.DATE, num);// num为增加的天数，可以改变的
        return format.format(ca.getTime());
    }

    /**
     * 返回当前月份的第一天和最后一天，格式：2017-02-01 00:00:00, 2017-02-28 23:59:59
     * @return
     */
    public static String[] getCurrentMonthFirstAndLastDay(){
        Calendar cale = Calendar.getInstance();

        // 获取当月第一天和最后一天
        SimpleDateFormat startFormat = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
        SimpleDateFormat endFormat = new SimpleDateFormat("yyyy-MM-dd 23:59:59");
        String firstday, lastday;
        // 获取前月的第一天
        cale = Calendar.getInstance();
        cale.add(Calendar.MONTH, 0);
        cale.set(Calendar.DAY_OF_MONTH, 1);
        firstday = startFormat.format(cale.getTime());
        // 获取前月的最后一天
        cale = Calendar.getInstance();
        cale.add(Calendar.MONTH, 1);
        cale.set(Calendar.DAY_OF_MONTH, 0);
        lastday = endFormat.format(cale.getTime());
//        System.out.println("本月第一天和最后一天分别是 ： " + firstday + " and " + lastday);
        return new String[]{firstday, lastday};

    }


    /**
     * 判断某一时间是否在一个区间内
     *
     * @param sourceTime
     *            时间区间,半闭合,如: 09:00:00-18:00:00
     * @param curTime
     *            需要判断的时间 如: 18:00:01
     * @return
     * @throws IllegalArgumentException
     */
    public static boolean isInTime(String sourceTime, String curTime) {
        if (sourceTime == null || !sourceTime.contains("-") || !sourceTime.contains(":")) {
            throw new IllegalArgumentException("Illegal Argument arg:" + sourceTime);
        }
        if (curTime == null || !curTime.contains(":")) {
            throw new IllegalArgumentException("Illegal Argument arg:" + curTime);
        }
        String[] args = sourceTime.split("-");
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        try {
            long now = sdf.parse(curTime).getTime();
            long start = sdf.parse(args[0]).getTime();
            long end = sdf.parse(args[1]).getTime();
            if (args[1].equals("00:00:00")) {
                args[1] = "24:00:00";
            }
            if (end < start) {
                if (now >= end && now < start) {
                    return false;
                } else {
                    return true;
                }
            }
            else {
                if (now >= start && now < end) {
                    return true;
                } else {
                    return false;
                }
            }
        } catch (ParseException e) {
            e.printStackTrace();
            throw new IllegalArgumentException("Illegal Argument arg:" + sourceTime);
        }
    }


    public static String getWeek(Date date){

        String[] weeks = {"星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int week_index = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if(week_index<0){
            week_index = 0;
        }
        return weeks[week_index];
    }



    public static void main(String[] args) throws ParseException {
        Date date = DateUtil.getRelativeDate(new Date(), -10);
        String startCreateTime = convertDateToString("yyyy-MM-dd 00:00:00", date);
        String stopCreateTime = convertDateToString("yyyy-MM-dd 00:00:00", new Date());

        System.out.println(getCurrentMonthFirstAndLastDay()[0] + "==" + getCurrentMonthFirstAndLastDay()[1]);
        System.out.println(isInTime("09:00:00-18:00:00", "18:00:01"));
    }
}
